package com.hyt.it.ogt.ks.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.hyt.it.ogt.ks.model.dto.CandidateAnswerSimpleVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.ks.api.kw.model.ObjectiveItemScoreDTO;
import com.hyt.it.ogt.ks.config.KsBizRunTimeException;
import com.hyt.it.ogt.ks.enums.BizStatusCode;
import com.hyt.it.ogt.ks.feign.KwClient;
import com.hyt.it.ogt.ks.mapper.CandidateAnswerBackupMapper;
import com.hyt.it.ogt.ks.mapper.CandidateAnswerMapper;
import com.hyt.it.ogt.ks.mapper.CandidateLogBackupMapper;
import com.hyt.it.ogt.ks.mapper.CandidateLogMapper;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswer;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswerBackup;
import com.hyt.it.ogt.ks.model.entity.CandidateLog;
import com.hyt.it.ogt.ks.model.entity.CandidateLogBackup;
import com.hyt.it.ogt.ks.service.ICandidateAnswerBackupService;
import com.hyt.it.ogt.ks.service.ICandidateAnswerService;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wuyingge
 * @ClassName CandidateAnswerBackupServiceImpl.java
 * @Description 考试答案详情表 服务实现类
 * @createTime 2021年11月15日 18:36:00
 */
@Slf4j
@Service
public class CandidateAnswerBackupServiceImpl extends BaseServiceImpl<CandidateAnswerBackupMapper, CandidateAnswerBackup>
        implements ICandidateAnswerBackupService {
    @Resource
    private CandidateAnswerBackupMapper candidateAnswerBackupMapper;
    @Resource
    private CandidateAnswerMapper candidateAnswerMapper;
    @Resource
    private ICandidateAnswerService iCandidateAnswerService;
    @Resource
    private KwClient kwClient;
    @Resource
    private CandidateLogBackupMapper candidateLogBackupMapper;
    @Resource
    private CandidateLogMapper candidateLogMapper;

    /**
     * 获取考生答案
     * @param
     * @return
     */
    @Override
    public List<CandidateAnswer> selectList(String examId, String examCandidateId, Integer maxScoreVer, Boolean isObjective) {
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.eq(CandidateAnswerBackup::getExamId, examId)
                .eq(CandidateAnswerBackup::getCandidateId, examCandidateId)
                .eq(CandidateAnswerBackup::getAnswerVer, maxScoreVer)
                .eq(CandidateAnswerBackup::getDelFlag, false);
        if(isObjective != null){
            query.eq(CandidateAnswerBackup::getObjectiveOrSubjective, isObjective);
        }
        List<CandidateAnswerBackup> backups = candidateAnswerBackupMapper.selectList(query);
        List<CandidateAnswer> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(e -> {
            CandidateAnswer answer = new CandidateAnswer();
            BeanUtils.copyProperties(e,answer);
            answers.add(answer);
        });
        return answers;
    }

    /**
     * 为整场考试统分进行查询
     * @param examId
     * @param candidateId
     * @return
     */
    @Override
    public List<CandidateAnswer> calculateAllStudentScores(String examId, String candidateId, String paperId, String paperVersion){
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.select(CandidateAnswerBackup::getItemId, CandidateAnswerBackup::getObjectiveAnswer, CandidateAnswerBackup::getId)
                .eq(CandidateAnswerBackup::getExamId,examId).eq(CandidateAnswerBackup::getCandidateId,candidateId)
                .eq(CandidateAnswerBackup::getPaperId, paperId).eq(CandidateAnswerBackup::getPaperVersion, paperVersion)
                .eq(CandidateAnswerBackup::getDelFlag,false);
        List<CandidateAnswerBackup> backups = candidateAnswerBackupMapper.selectList(query);
        List<CandidateAnswer> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(e -> {
            CandidateAnswer answer = new CandidateAnswer();
            BeanUtils.copyProperties(e,answer);
            answers.add(answer);
        });
        return answers;
    }


    /**
     * 兴业银行推送大易查询
     * @param candidateId
     * @param examId
     * @param paperId
     * @param paperVersion
     * @return
     */
    @Override
    public List<CandidateAnswer> getXyEvalResult(String candidateId, String examId, String paperId, String paperVersion){
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.eq(CandidateAnswerBackup::getCandidateId,candidateId)
                .select(CandidateAnswerBackup::getObjectiveAnswer, CandidateAnswerBackup::getForceAnswer,
                        CandidateAnswerBackup::getItemSerialNumber, CandidateAnswerBackup::getAnswerTime)
                .eq(CandidateAnswerBackup::getExamId,examId)
                .eq(CandidateAnswerBackup::getDelFlag,false)
                .eq(CandidateAnswerBackup::getPaperId,paperId).eq(CandidateAnswerBackup::getPaperVersion,paperVersion);
        List<CandidateAnswerBackup> backups = candidateAnswerBackupMapper.selectList(query);
        List<CandidateAnswer> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(e -> {
            CandidateAnswer answer = new CandidateAnswer();
            BeanUtils.copyProperties(e, answer);
            answers.add(answer);
        });
        return answers;
    }

    /**
     * 将答案从表中转存至备份表
     * @return
     */
    @Override
    public Boolean moveAnswerToBackup(String ... candidateIds){
        if(Objects.isNull(candidateIds) || candidateIds.length == 0){
            log.error("-----收到考生答题转存备份库，考生id集合为空--------");
        }
        log.info("-----收到考生答题转存备份库，考生id集合数量为:{}",candidateIds.length);
        List<String> cIds = new ArrayList<>(candidateIds.length);
        Collections.addAll(cIds,candidateIds);
        //1: 先取出数据
        LambdaQueryWrapper<CandidateAnswer> caQuery = Wrappers.lambdaQuery();
        caQuery.in(CandidateAnswer::getCandidateId,cIds);
        List<CandidateAnswer> answers = candidateAnswerMapper.selectList(caQuery);
        if(CollectionUtils.isEmpty(answers)){
            log.error("-----收到考生答题转存备份库，考生id集合为{},查询到考生答题表数据为空--------", Arrays.toString(candidateIds));
            return Boolean.TRUE;
        }

        //2：存入备份库
        //2.1转对象
        List<CandidateAnswerBackup> backups = new ArrayList<>(answers.size());
        answers.stream().forEach(a -> {
            CandidateAnswerBackup backup = new CandidateAnswerBackup();
            BeanUtils.copyProperties(a,backup);
            backups.add(backup);
        });
        //2.2备份入库
        //this.saveBatch(backups);
        candidateAnswerBackupMapper.saveBatch(backups);

        //3:设置kw_exam_Candidate is_backup = 1
        Set<String> backupCandidateIds = backups.stream().map(CandidateAnswerBackup::getCandidateId).collect(Collectors.toSet());
        String rsp = kwClient.updateExamCandidateAnswerIsBackup(new ArrayList<>(backupCandidateIds));
        log.info("调用考务系统更新考试考生表isBackup,返回信息为:【{}】",rsp);
        if(StringUtils.isBlank(rsp)){
            log.error("调用考务系统更新考试考生表isBackup失败");
            throw new KsBizRunTimeException();
        }
        ApiResponse<Boolean> response = ApiResponse.ConvertRet(rsp,Boolean.class);
        if(!Objects.equals(BizStatusCode.KW_SUCCESS_OK.getCode(),response.getCode()) || !Objects.equals(Boolean.TRUE,response.getData())){
            log.error("调用考务系统更新考试考生表isBackup失败");
            throw new KsBizRunTimeException();
        }

        //4:清除原表中的数据。释放空间
        List<String> answerIds = backups.stream().map(CandidateAnswerBackup::getId).collect(Collectors.toList());
        int records = candidateAnswerMapper.deleteBatchIds(answerIds);
        if(records != backups.size()){
            log.error("考生答题转存备份库之后，清理原考生答题表数据失败");
            throw new KsBizRunTimeException();
        }
        return Boolean.TRUE;
    }

    /**
     * 移动回原表，当撤销试卷时
     * @param examId
     * @param candidateId
     * @return
     */
    public Boolean cancelPackageCommit(String examId, String candidateId,Integer logBackup){
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.eq(CandidateAnswerBackup::getExamId,examId).eq(CandidateAnswerBackup::getCandidateId,candidateId);
        List<CandidateAnswerBackup> backups = this.baseMapper.selectList(query);
        List<CandidateAnswer> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(b -> {
            CandidateAnswer answer = new CandidateAnswer();
            BeanUtils.copyProperties(b,answer);
            answers.add(answer);
        });
        iCandidateAnswerService.saveBatch(answers);
        //处理考生事件的备份表
        List<String> logBackupIds = new ArrayList<>();
        if(Objects.equals(1,logBackup)){
            LambdaQueryWrapper<CandidateLogBackup> logQuery = Wrappers.lambdaQuery();
            logQuery.eq(CandidateLogBackup::getExamId,examId).eq(CandidateLogBackup::getCandidateId,candidateId);
            List<CandidateLogBackup> logBackups = candidateLogBackupMapper.selectList(logQuery);
            List<CandidateLog> logs = new ArrayList<>(logBackups.size());
            logBackups.stream().forEach(l -> {
                CandidateLog log = new CandidateLog();
                BeanUtils.copyProperties(l,log);
                logs.add(log);
            });
            candidateLogMapper.batchSave(logs);
            logBackupIds = logBackups.stream().map(CandidateLogBackup::getId).collect(Collectors.toList());
        }
        //设置回备份的状态
        String rsp = kwClient.updateExamCandidateBackupWenRodoExam(candidateId);
        log.info("撤销交卷调用考务系统更新考生表备份字段，返回信息为:【{}】",rsp);
        if(StringUtils.isBlank(rsp)){
            log.info("撤销交卷调用考务系统更新考生表备份字段失败，返回信息为空");
            throw new KsBizRunTimeException();
        }
        ApiResponse<Boolean> updateRes = ApiResponse.ConvertRet(rsp,Boolean.class);
        if(!Objects.equals(updateRes.getCode(),BizStatusCode.KW_SUCCESS_OK.getCode()) || Objects.equals(Boolean.FALSE,updateRes.getData())){
            log.error("撤销交卷调用考务系统更新考生表备份字段失败，返回信息为:【{}】",rsp);
            throw new KsBizRunTimeException();
        }
        //删除备份表中的数据
        if(!CollectionUtils.isEmpty(backups)){
            candidateAnswerBackupMapper.deleteBatchIds(backups.stream().map(CandidateAnswerBackup::getId).collect(Collectors.toList()));
        }
        if(!CollectionUtils.isEmpty(logBackupIds)){
            candidateLogBackupMapper.deleteBatchIds(logBackupIds);
        }
        return Boolean.TRUE;
    }

    /**
     * 当考生选择重新考试时，处理已备份的答题信息
     * @param examId
     * @param candidateId
     * @param redoExamCount
     * @return
     */
    public Boolean redoExam(String examId, String candidateId, Integer redoExamCount){
        //1:先将数据查出来
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.eq(CandidateAnswerBackup::getExamId,examId).eq(CandidateAnswerBackup::getCandidateId,candidateId);
        List<CandidateAnswerBackup> backups = this.baseMapper.selectList(query);
        List<String> backupIds = backups.stream().map(CandidateAnswerBackup::getId).collect(Collectors.toList());
        //2:将数据重新存回去
        candidateAnswerBackupMapper.redoExam(examId,candidateId,redoExamCount);
        //3:将备份表里的数据设置成已删除
        if(CollectionUtils.isEmpty(backupIds)){
            return Boolean.TRUE;
        }
        candidateAnswerBackupMapper.updateIsDefByIds(backupIds);
        //4:将答题及事件是否备份字段设置回0
        String rep = kwClient.updateExamCandidateBackupWenRodoExam(candidateId);
        log.info("调用考务系统更新考生表备份字段，收到返回信息为：【{}】",rep);
        if(StringUtils.isBlank(rep)){
            log.error("调用考务系统更新考生表备份字段，更新考试考生表字段状态失败");
            throw new KsBizRunTimeException(BizStatusCode.UPDATE_CANDIDATE_BACKUP_ERROR.getCode(),
                    BizStatusCode.UPDATE_CANDIDATE_BACKUP_ERROR.getMsg());
        }
        ApiResponse<Boolean> updateResponse = ApiResponse.ConvertRet(rep,Boolean.class);
        if(!Objects.equals(updateResponse.getCode(),BizStatusCode.KW_SUCCESS_OK.getCode()) || !Objects.equals(Boolean.TRUE,updateResponse.getData())){
            log.error("调用考务系统更新考生表备份字段，更新考试考生表字段状态失败,kw返回信息为:【{}】------",updateResponse);
            throw new KsBizRunTimeException(BizStatusCode.UPDATE_CANDIDATE_BACKUP_ERROR.getCode(),
                    BizStatusCode.UPDATE_CANDIDATE_BACKUP_ERROR.getMsg());
        }
        return Boolean.TRUE;
    }

    /**
     * 考生自己查询考试成绩
     * @param examId
     * @param admissionNumber
     * @param maxScoreVer
     * @return
     */
    @Override
    public List<CandidateAnswer> getAnswerList(String examId, String admissionNumber, Integer maxScoreVer){
        LambdaQueryWrapper<CandidateAnswerBackup> query = Wrappers.lambdaQuery();
        query.eq(CandidateAnswerBackup::getExamId,examId).eq(CandidateAnswerBackup::getAdmissionNumber,admissionNumber)
                .eq(CandidateAnswerBackup::getAnswerVer,maxScoreVer);
        List<CandidateAnswerBackup> backups = candidateAnswerBackupMapper.selectList(query);
        List<CandidateAnswer> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(e -> {
            CandidateAnswer answer = new CandidateAnswer();
            BeanUtils.copyProperties(e,answer);
            answers.add(answer);
        });
        return answers;
    }

    @Override
    public List<ObjectiveItemScoreDTO> getObjectiveItemScore(String examId, String candidateId, String paperId, String paperVersion) {
        return baseMapper.getObjectiveItemScore(examId, candidateId, paperId, paperVersion);
    }

    @Override
    public List<CandidateAnswerSimpleVO> selectSimpleAnswerBackupList(String examId, List<String> examCandidateIds, List<Integer> maxScoreVers) {
        List<CandidateAnswerSimpleVO> backups = candidateAnswerBackupMapper.selectSimpleAnswerBackupList(examId, examCandidateIds, maxScoreVers);
        List<CandidateAnswerSimpleVO> answers = new ArrayList<>(backups.size());
        backups.stream().forEach(e -> {
            CandidateAnswerSimpleVO answer = new CandidateAnswerSimpleVO();
            BeanUtils.copyProperties(e,answer);
            answers.add(answer);
        });
        return answers;
    }
}
